package objectClasses;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;

public class Category {
	/**
	 * A list of all the Categories
	 */
	public static String CATEGORY_FILE = "category.txt";

	/**
	 * A boolean value that represents weather the categories have been loaded
	 * or not
	 */
	private static boolean loaded = false;

	/**
	 * The name of the category in the contest
	 */
	private String catName;

	/**
	 * List of contestant in this category
	 */
	private ArrayList<UserInfo> contestants = new ArrayList<UserInfo>();

	/**
	 * A list of judges in this category
	 */
	private ArrayList<UserInfo> judges = new ArrayList<UserInfo>();

	/**
	 * List of all the Categories in the contest
	 */
	private static final ArrayList<Category> CATEGORIES = new ArrayList<Category>();

	/**
	 * Constructs a new Category with a given name
	 * 
	 * @param name
	 *            of the category           
	 * @author Diana Gorun
	 */
	public Category(String name) {
		catName = name;
		judges = new ArrayList<UserInfo>();
		contestants = new ArrayList<UserInfo>();
	}

	/**
	 * Adds a given category to the list of categories
	 * @author Diana Gorun
	 * @param c
	 */
	public static void addCategory(Category c) {
		loadCategories();
		if (!CATEGORIES.contains(c)) {
			CATEGORIES.add(c);
			c.writeCategoryToFile();
		}
	}

	/**
	 * Adds a contestant to the list of contestants. This method does not update
	 * the file
	 * @param j
	 */
	public void addContestants(UserInfo j) {
		if (j.getUserType() == 'C') {
			contestants.add(j);
		}
	}

	/**
	 * Adds a new Judge to the list of judges. This methods also writes the
	 * judge to the Category file
	 * @author Diana Gorun
	 * @param j
	 */
	public void addJudges(UserInfo j) {
		if (j.getUserType() == 'J' && !judges.contains(j)) {
			judges.add(j);
		}
		updateCategory();
	}

	/**
	 * Deletes this category from the file
	 * @author Diana Gorun
	 */
	private void deleteFromFile() {
		try {
			BufferedReader in = new BufferedReader(
					new FileReader(CATEGORY_FILE));
			String line;
			String temp[];
			StringBuilder buf = new StringBuilder();
			while ((line = in.readLine()) != null) {
				temp = line.split(":");
				if (!temp[0].equals(catName)) {
					buf.append(line);
					buf.append("\r\n");
				}
			}

			in.close();

			// modify file contents

			FileWriter fstream = new FileWriter(CATEGORY_FILE);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(buf.toString());
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("File did not exist, created it");
			File f = new File(CATEGORY_FILE);
			try {
				f.createNewFile();
				deleteFromFile();
			} catch (IOException e1) {
				System.out.print("Could not created a file?");
			}
		}

	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof Category) {
			Category c = (Category) o;
			if (c.getName().equals(catName)) {
				return true;
			}
			return false;
		}
		return false;
	}

	/**
	 * Returns a list of all the categories in the even
	 * @author Diana Gorun
	 * @return
	 */
	public static ArrayList<Category> getCategories() {
		loadCategories();
		return CATEGORIES;
	}

	/**
	 * Returns the category with the given Name
	 * @author Diana Gorun
	 * @param Name
	 */
	public static Category getCategory(String Name) {
		loadCategories();
		int index = CATEGORIES.indexOf(new Category(Name));
		if (index == -1) {
			return null;
		}
		return CATEGORIES.get(index);
	}

	/**
	 * Returns a list of contestants that are competing in this category
	 * 
	 * @return
	 */
	public ArrayList<UserInfo> getContestants() {
		return contestants;
	}

	/**
	 * Returns the entries submitted in this category
	 * @author Diana Gorun
	 * @return
	 */
	public LinkedList<Entry> getEntries() {
		return Database.getEntriesBasedOnCat(catName);
	}

	/**
	 * Returns a list of Judges that are judging in this Category
	 * @author Diana Gorun
	 * @return
	 */
	public ArrayList<UserInfo> getJudges() {
		return judges;
	}

	/**
	 * Returns the name of the category
	 * @author Diana Gorun
	 * @return
	 */
	public String getName() {
		return catName;
	}
/**
 * Loads all the Categories from file into memory
 * @author Diana Gorun
 */
	private static void loadCategories() {
		if (loaded == false) {
			File file = new File(CATEGORY_FILE);
			String cName = "";
			String splitVal[];
			Category c;

			if (!file.isFile()) {
				try {
					file.createNewFile();
				} catch (IOException e) {
					System.out.print("Load File Error");
				}
			}

			BufferedReader r = null;

			try {
				r = new BufferedReader(new FileReader(file));
				while ((cName = r.readLine()) != null) {
					splitVal = cName.split(":");
					c = new Category(splitVal[0]);
					CATEGORIES.add(c);
					loadJudges(splitVal, c);
					loadContestants(c);
				}
				r.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			loaded = true;
		}
	}
/**
 * 
 * @param cat
 */
	private static void loadContestants(Category cat) {
		UserInfo j;
		LinkedList<Entry> entries = Database
				.getEntriesBasedOnCat(cat.getName());
		String temp[];
		for (int i = 0; i < entries.size(); i++) {
			try {
				temp = User.getUserInfo(entries.get(i).getUsername());
				j = new UserInfo('C', temp[0], temp[1], temp[2], temp[3],
						temp[4]);
				cat.addContestants(j);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Loads all the judges form file to memory
	 * @author Diana Gorun
	 * @param userName
	 * @param cat
	 */
	private static void loadJudges(String userName[], Category cat) {
		UserInfo j;
		String temp[];
		for (int i = 1; i < userName.length; i++) {
			try {
				temp = User.getUserInfo(userName[i]);
				j = new UserInfo('J', temp[0], temp[1], temp[2], temp[3],
						temp[4]);
				cat.addJudges(j);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Removes a given category from the list of categories
	 * @author Diana Gorun
	 * @param c
	 */
	public static void removeCategory(Category c) {
		loadCategories();
		CATEGORIES.remove(c);
		c.deleteFromFile();
	}

	/**
	 * Removes the given judge from this category
	 * @author Diana Gorun
	 * @param j
	 */
	public void removeJudge(UserInfo j) {
		judges.remove(j);
		updateCategory();
	}

	/**
	 * Removes a given judge from all Categories
	 * @author Diana Gorun
	 * @param j
	 */
	public static void removeJudgeFromAllCategoreies(UserInfo j) {
		for (Category c : CATEGORIES) {
			c.getJudges().remove(j);
		}
		updateFile();
	}

	/**
	 * Updates the whole file
	 * @author Diana Gorun
	 */
	private static void updateFile() {
		try {

			StringBuilder buf = new StringBuilder();
			for (Category c : CATEGORIES) {
				buf.append(c.getName());
				for (UserInfo u : c.getJudges()) {
					buf.append(":");
					buf.append(u.getUserName());
				}
				buf.append("\r\n");
			}

			// modify file contents

			FileWriter fstream = new FileWriter(CATEGORY_FILE);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(buf.toString());

			// Close the output stream
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("File did not exist, created it");
			File f = new File(CATEGORY_FILE);
			try {
				f.createNewFile();
				updateFile();
			} catch (IOException e1) {
				System.out.print("Could not created a file?");
			}
		}

	}

	/**
	 * Sets the name of the Category
	 * @author Diana Gorun
	 * @param name
	 */
	public void setName(String name) {
		catName = name;
		updateCategory();
	}

	@Override
	public String toString() {
		return catName;
	}

	/**
	 * Updates the file with the information from this category
	 * @author Diana Gorun
	 */
	private void updateCategory() {
		try {
			BufferedReader in = new BufferedReader(
					new FileReader(CATEGORY_FILE));
			String line;
			StringBuilder buf = new StringBuilder();
			String temp[];
			while ((line = in.readLine()) != null) {
				temp = line.split(":");
				if (temp[0].equalsIgnoreCase(catName)) {
					buf.append(catName);
					for (UserInfo u : judges) {
						buf.append(":");
						buf.append(u.getUserName());
					}
					buf.append("\r\n");
				} else {
					buf.append(line);
					buf.append("\r\n");
				}
			}

			in.close();

			// modify file contents

			FileWriter fstream = new FileWriter(CATEGORY_FILE);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(buf.toString());

			// Close the output stream
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("File did not exist, created it");
			File f = new File(CATEGORY_FILE);
			try {
				f.createNewFile();
				updateCategory();
			} catch (IOException e1) {
				System.out.print("Could not created a file?");
			}
		}

	}

	/**
	 * Writes a category to file
	 * @author Diana Gorun
	 */
	private void writeCategoryToFile() {
		try {
			BufferedReader in = new BufferedReader(
					new FileReader(CATEGORY_FILE));
			String line;
			StringBuilder buf = new StringBuilder();
			while ((line = in.readLine()) != null) {
				buf.append(line);
				buf.append("\r\n");
			}

			in.close();

			// modify file contents

			FileWriter fstream = new FileWriter(CATEGORY_FILE);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(buf.toString());
			out.write(catName);
			for (UserInfo j : judges) {
				buf.append(":");
				buf.append(j.getUserName());
			}
			out.write("\r\n");
			// Close the output stream
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("File did not exist, created it");
			File f = new File(CATEGORY_FILE);
			try {
				f.createNewFile();
				writeCategoryToFile();
			} catch (IOException e1) {
				System.out.print("Could not created a file?");
			}
		}

	}

	public static void main(String[] arg) {
		Category c = new Category("Basket");
		Category.addCategory(c);
		// Category.getCategory("Something").setName("Basket");

		// User.Register("user", "pass", "email", "first", "last", "phone",
		// 'J');
		String user[];
		UserInfo u;
		try {
			user = User.getUserInfo("user");
			u = new UserInfo('J', user[0], user[1], user[2], user[3], user[4]);
			Category.getCategory("Basket").addJudges(u);
			System.out.print(Category.getCategory("Basket").getJudges());
			Category.removeJudgeFromAllCategoreies(u);
			System.out.print(Category.getCategory("Basket").getJudges());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}
